#
# %CopyrightBegin%
#
# Copyright Ericsson AB 1996-2023. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# %CopyrightEnd%
#

include $(ERL_TOP)/make/target.mk
include ../vsn.mk
include $(ERL_TOP)/make/$(TARGET)/otp.mk
-include $(TARGET)/gen_git_version.mk

ENABLE_ALLOC_TYPE_VARS = @ENABLE_ALLOC_TYPE_VARS@
JIT_ENABLED=@JIT_ENABLED@
JIT_ARCH=@JIT_ARCH@
DTRACE_ENABLED=@DTRACE_ENABLED@
DTRACE_ENABLED_2STEP=@DTRACE_ENABLED_2STEP@
USE_VM_PROBES=@USE_VM_PROBES@
LIBS = @LIBS@
Z_LIB=@Z_LIB@
CROSS_COMPILING = @CROSS_COMPILING@
NO_INLINE_FUNCTIONS=false
USING_VC=@MIXED_VC@

OPCODE_TABLES = \
    $(ERL_TOP)/lib/compiler/src/genop.tab \
    beam/predicates.tab \
    beam/generators.tab

ifeq ($(FLAVOR),)
ifeq ($(JIT_ENABLED),yes)
override FLAVOR=jit
else
override FLAVOR=emu
endif
endif

ifeq ($(FLAVOR),jit)
ifneq ($(JIT_ENABLED),yes)
$(error "JIT is not supported")
endif
else
JIT_ENABLED=no
endif

ifeq ($(FLAVOR),jit)
OMIT_OMIT_FP=yes
OPCODE_TABLES += \
    beam/jit/$(JIT_ARCH)/ops.tab \
    beam/jit/$(JIT_ARCH)/predicates.tab \
    beam/jit/$(JIT_ARCH)/generators.tab
else
OMIT_OMIT_FP=no
OPCODE_TABLES += \
    beam/emu/ops.tab \
    beam/emu/predicates.tab \
    beam/emu/generators.tab \
    beam/emu/macros.tab \
    beam/emu/instrs.tab \
    beam/emu/arith_instrs.tab \
    beam/emu/bif_instrs.tab \
    beam/emu/bs_instrs.tab \
    beam/emu/float_instrs.tab \
    beam/emu/map_instrs.tab \
    beam/emu/msg_instrs.tab \
    beam/emu/select_instrs.tab \
    beam/emu/trace_instrs.tab
endif


DEBUG_CFLAGS = @DEBUG_CFLAGS@
CONFIGURE_CFLAGS = @CFLAGS@

#
# Run this make file with TYPE set to the type of emulator you want.
# Different versions of the emulator for different uses. The default
# is "debug". For a normal version use "opt".
#
DEFS=@DEFS@
THR_DEFS=@EMU_THR_DEFS@
M4FLAGS=
CREATE_DIRS=

LDFLAGS=@LDFLAGS@
ARFLAGS=rc
TYPE_LIBS=

PROFILE_COMPILER=@PROFILE_COMPILER@
PROFILE_MARKER=
ifeq ($(PROFILE),generate)
PROFILE_MARKER=_pg
else
ifeq ($(PROFILE),use)
PROFILE_MARKER=_pu
endif
endif

ifeq ($(PROFILE_COMPILER), gcc)
PROFILE_GENERATE=-fprofile-generate
PROFILE_USE=-fprofile-use -fprofile-correction
PROFILE_USE_DEPS=$(OBJDIR)/%_pu.gcda
endif
ifeq ($(PROFILE_COMPILER), clang)
PROFILE_GENERATE=-fprofile-instr-generate
PROFILE_USE=-fprofile-instr-use=$(OBJDIR)/default.profdata
PROFILE_USE_DEPS=$(OBJDIR)/default.profdata
endif

DIRTY_SCHEDULER_TEST=@DIRTY_SCHEDULER_TEST@

ifeq ($(TYPE),debug)
TYPEMARKER = .debug
TYPE_FLAGS = $(DEBUG_CFLAGS) -DDEBUG
ENABLE_ALLOC_TYPE_VARS += debug
ifeq ($(TARGET),win32)
TYPE_FLAGS += -DNO_JUMP_TABLE
LDFLAGS += -g
endif
else

ifeq ($(TYPE),gcov)
TYPEMARKER = .gcov
TYPE_FLAGS = $(DEBUG_CFLAGS) -DERTS_GCOV -DNO_JUMP_TABLE -fprofile-arcs -ftest-coverage -O0 -DERTS_CAN_INLINE=0 -DERTS_INLINE=
ifneq ($(findstring solaris,$(TARGET)),solaris)
TYPE_LIBS = -lgcov
endif
ENABLE_ALLOC_TYPE_VARS += debug
else

ifeq ($(TYPE),valgrind)
TYPEMARKER = .valgrind
TYPE_FLAGS = $(DEBUG_CFLAGS) -DVALGRIND -DNO_JUMP_TABLE
ENABLE_ALLOC_TYPE_VARS += valgrind
else

ifeq ($(TYPE),asan)
PURIFY =
TYPEMARKER = .asan
TYPE_FLAGS = $(DEBUG_CFLAGS) -fsanitize=address -fsanitize-recover=address -fno-omit-frame-pointer -DADDRESS_SANITIZER
LDFLAGS += -fsanitize=address
ENABLE_ALLOC_TYPE_VARS += asan
else

ifeq ($(TYPE),gprof)
TYPEMARKER = .gprof
TYPE_FLAGS = @CFLAGS@ -DGPROF -pg -DERTS_CAN_INLINE=0 -DERTS_INLINE=
LDFLAGS += -pg
ENABLE_ALLOC_TYPE_VARS += gprof
NO_INLINE_FUNCTIONS=true
else

ifeq ($(TYPE),lcnt)
TYPEMARKER = .lcnt
TYPE_FLAGS = @CFLAGS@ -DERTS_ENABLE_LOCK_COUNT
ENABLE_ALLOC_TYPE_VARS += lcnt
else

ifeq ($(TYPE),frmptr)
OMIT_OMIT_FP=yes
TYPEMARKER = .frmptr
TYPE_FLAGS = @CFLAGS@ -DERTS_FRMPTR
else

ifeq ($(TYPE),icount)
TYPEMARKER = .icount
TYPE_FLAGS = @CFLAGS@ -DERTS_OPCODE_COUNTER_SUPPORT
else

# If type isn't one of the above, it *is* opt type...
override TYPE=opt
TYPEMARKER =
TYPE_FLAGS = @CFLAGS@
endif
endif
endif
endif
endif
endif
endif
endif

LIBS += $(TYPE_LIBS)

ORIG_LIBS:= $(LIBS)

comma:=,
space:=
space+=

STATIC_NIFS=@STATIC_NIFS@
ifneq ($(STATIC_NIFS),no)
ifeq ($(STATIC_NIFS),yes)
STATIC_NIFS=$(ERL_TOP)/lib/asn1/priv/lib/$(TARGET)/asn1rt_nif.a
ifeq ($(wildcard $(ERL_TOP)/lib/crypto/SKIP),)
	STATIC_NIFS+=$(ERL_TOP)/lib/crypto/priv/lib/$(TARGET)/crypto$(TYPEMARKER).a
endif
endif
STATIC_NIFS:=$(subst $(comma),$(space),$(STATIC_NIFS))
endif

STATIC_DRIVERS=@STATIC_DRIVERS@
ifneq ($(STATIC_DRIVERS),no)
ifeq ($(STATIC_DRIVERS),yes)
STATIC_DRIVERS=
endif
STATIC_DRIVERS:=$(subst $(comma),$(space),$(STATIC_DRIVERS))
endif


#
# NOTE: When adding a new type update ERL_BUILD_TYPE_MARKER in sys/unix/sys_drivers.c
#

FLAVOR_MARKER=.$(FLAVOR)
ENABLE_ALLOC_TYPE_VARS += nofrag
ifeq ($(DIRTY_SCHEDULER_TEST),yes)
DS_TEST=yes
THR_DEFS += -DERTS_DIRTY_SCHEDULERS_TEST
else # DIRTY_SCHEDULER_TEST
DS_TEST=no
endif # DIRTY_SCHEDULER_TEST

TF_MARKER=$(TYPEMARKER)$(FLAVOR_MARKER)

ifeq ($(TYPE)-@HAVE_VALGRIND@,valgrind-no)
VOID_EMULATOR = '*** valgrind emulator disabled by configure'
else
VOID_EMULATOR =
endif

OPSYS=@OPSYS@

sol2CFLAGS=
linuxCFLAGS=
darwinCFLAGS=-DDARWIN
noopsysCFLAGS=
OPSYSCFLAGS=$($(OPSYS)CFLAGS)
ARCH=@ARCH@
ultrasparcCFLAGS=-Wa,-xarch=v8plusa
ARCHCFLAGS=$($(ARCH)CFLAGS)

ERTS_BUILD_FALLBACK_POLL=@ERTS_BUILD_FALLBACK_POLL@

#
#
#
SHELL   = /bin/sh
CC      = @CC@
ifeq ($(TARGET),win32)
ifeq ($(TYPE),debug)
EMU_CC  = @CC@
else
EMU_CC  = @EMU_CC@
endif
TYPE_FLAGS += -DSTATIC_ERLANG_DRIVER
else
EMU_CC  = @EMU_CC@
endif
WFLAGS  = @WFLAGS@
CFLAGS  = @STATIC_CFLAGS@ $(TYPE_FLAGS) $(FLAVOR_FLAGS) $(DEFS) $(WFLAGS) $(THR_DEFS) $(ARCHCFLAGS) $(GIT_VSN)
ifeq ($(FLAVOR),jit)
CFLAGS  += -DBEAMASM=1
ENABLE_ALLOC_TYPE_VARS += beamasm
endif
CXXFLAGS = $(filter-out -Werror=implicit -Wstrict-prototypes -Wmissing-prototypes -Wdeclaration-after-statement,$(CFLAGS)) @CXXFLAGS@
HCC     = @HCC@
LD      = @LD@
DEXPORT = @DEXPORT@
RANLIB  = @RANLIB@
STRIP   = strip
PERL    = @PERL@
MKDIR	= @MKDIR@

USING_MINGW=@MIXED_MINGW@

ifeq ($(TARGET),win32)
LIB_PREFIX=
LIB_SUFFIX=.lib
EXE_SUFFIX=.exe
else
LIB_PREFIX=lib
LIB_SUFFIX=.a
EXE_SUFFIX=
endif

ifeq (@EMU_LOCK_CHECKING@,yes)
NO_INLINE_FUNCTIONS=true
endif

ifneq ($(filter tile-%,$(TARGET)), )
# -O2 generally produces faster for tile-cc, because the code is smaller.
# Since tile-cc looks like gcc, we need to override the normal gcc -O3 setting.
OPT_LEVEL = -O2
else
OPT_LEVEL = -O3
endif

ifeq ($(GCC),yes)
ifeq ($(NO_INLINE_FUNCTIONS),true)
GEN_OPT_FLGS = $(OPT_LEVEL) -fno-inline-functions
else
ifeq ($(OMIT_OMIT_FP),yes)
GEN_OPT_FLGS = $(OPT_LEVEL) -fno-omit-frame-pointer
else
GEN_OPT_FLGS = $(OPT_LEVEL) -fomit-frame-pointer
endif
endif
UNROLL_FLG = -funroll-loops
else
ifeq ($(TARGET), win32)
GEN_OPT_FLGS = $(OPT_LEVEL)
UNROLL_FLG = 
RC=rc.sh
ifeq ($(USING_MINGW), yes)
RES_EXT = @OBJEXT@
MAKE_PRELOAD_EXTRA += " -windres"
else
RES_EXT=res
endif
else
GEN_OPT_FLGS = 
UNROLL_FLG = 
RC=false
endif
endif

CS_CFLAGS_ = $(TYPE_FLAGS) $(DEFS) $(WFLAGS)
ifeq ($(GCC),yes)
CS_CFLAGS = $(subst -O2, $(GEN_OPT_FLGS) $(UNROLL_FLG), $(CS_CFLAGS_))
else
CS_CFLAGS = $(CS_CFLAGS_)
endif
CS_LDFLAGS = $(LDFLAGS)
CS_LIBS = -L../lib/internal/$(TARGET) -lerts_internal$(TYPEMARKER) @ERTS_INTERNAL_X_LIBS@ @SOCKET_LIBS@

LIBS	+= @TERMCAP_LIB@ -L../lib/internal/$(TARGET) @ERTS_INTERNAL_X_LIBS@

ifdef Z_LIB
# Use shared zlib library
LIBS += $(Z_LIB)
DEPLIBS =
else
DEPLIBS=$(ZLIB_LIBRARY)
ifeq ($(TARGET),win32)
LIBS    += -L$(ZLIB_OBJDIR) -lz
else
# Build on darwin fails if -lz is used
LIBS += $(ZLIB_LIBRARY)
endif
endif

ifeq ($(TARGET),win32)
LIBS    += -L$(ERL_TOP)/erts/emulator/pcre/obj/$(TARGET)/$(TYPE) -lepcre
else
LIBS    += $(ERL_TOP)/erts/emulator/pcre/obj/$(TARGET)/$(TYPE)/$(LIB_PREFIX)epcre$(LIB_SUFFIX)
endif

EPCRE_LIB = $(ERL_TOP)/erts/emulator/pcre/obj/$(TARGET)/$(TYPE)/$(LIB_PREFIX)epcre$(LIB_SUFFIX)
DEPLIBS += $(EPCRE_LIB)

DEPLIBS += $(RYU_LIBRARY)
ifeq ($(TARGET),win32)
LIBS += -L$(RYU_OBJDIR) -lryu
else
# Build on darwin fails if -lryu is used
LIBS += $(RYU_LIBRARY)
endif

DEPLIBS += $(OPENSSL_LIB)
ifeq ($(TARGET),win32)
LIBS += -L$(OPENSSL_OBJDIR) -l$(OPENSSL_LIB_NAME)
else
# Build on darwin fails if -l$(OPENSSL_LIB_NAME) is used
LIBS += $(OPENSSL_LIB)
endif

LIBSCTP = @LIBSCTP@

ORG_THR_LIBS=@EMU_THR_LIBS@
THR_LIB_NAME=@EMU_THR_LIB_NAME@

ERTS_LIB_DIR = $(ERL_TOP)/erts/lib_src
ERTS_LIB = $(ERTS_LIB_DIR)/obj/$(TARGET)/$(TYPE)/MADE
DEPLIBS += $(ERTS_LIB)

THR_LIBS=$(subst -l$(THR_LIB_NAME),-l$(THR_LIB_NAME)$(TYPEMARKER), \
	   $(subst -lerts_internal_r,-lerts_internal_r$(TYPEMARKER),$(ORG_THR_LIBS)))

LIBS += $(THR_LIBS)

ifneq ($(findstring erts_internal_r, $(THR_LIBS)),erts_internal_r)

ifneq ($(strip $(THR_LIB_NAME)),)
ERTS_INTERNAL_LIB=erts_internal_r
else
ERTS_INTERNAL_LIB=erts_internal
endif

LIBS += -l$(ERTS_INTERNAL_LIB)$(TYPEMARKER)

endif # erts_internal_r

ifneq ($(TARGET),arm-unknown-linux-androideabi)
LIBS += @LIBRT@
endif

LIBS += @LIBCARBON@

TTF_DIR=$(TARGET)/$(TYPE)/$(FLAVOR)
CREATE_DIRS += $(TTF_DIR)

# create obj dirs for emulator, pcre and zlib

OBJDIR = obj/$(TTF_DIR)

CREATE_DIRS += $(OBJDIR) \
	pcre/obj/$(TARGET)/$(TYPE) \
	$(ZLIB_OBJDIR) \
	$(RYU_OBJDIR) \
	$(OPENSSL_OBJDIR)

ifeq ($(FLAVOR),jit)
CREATE_DIRS+=$(OBJDIR)/asmjit/ $(OBJDIR)/asmjit/core $(OBJDIR)/asmjit/$(JIT_ARCH)
CREATE_DIRS+=$(TTF_DIR)/asmjit $(TTF_DIR)/asmjit/core $(TTF_DIR)/asmjit/$(JIT_ARCH)
endif

BINDIR = $(ERL_TOP)/bin/$(TARGET)
CREATE_DIRS += $(BINDIR)

ERLANG_OSTYPE = @ERLANG_OSTYPE@

ENABLE_ALLOC_TYPE_VARS += @ERLANG_OSTYPE@

ifeq ($(TARGET), win32)
FLAVOR_EXECUTABLE = beam$(TF_MARKER).dll
EMULATOR_LIB = libbeam.lib
else
FLAVOR_EXECUTABLE = beam$(TF_MARKER)
EMULATOR_LIB = libbeam.a
PROFILE_EXECUTABLE = beam.prof$(TF_MARKER)
endif
CS_EXECUTABLE = erl_child_setup$(TYPEMARKER)

ifeq ($(PROFILE), generate)
FLAVOR_EXECUTABLE = $(PROFILE_EXECUTABLE)
ifeq ($(PROFILE_COMPILER), gcc)
PROFILE_LDFLAGS = -fprofile-generate
endif
ifeq ($(PROFILE_COMPILER), clang)
PROFILE_LDFLAGS = -fprofile-instr-generate
endif
endif

ifeq ($(TARGET), win32)
PRIMARY_EXECUTABLE=beam$(TYPEMARKER).smp.dll
else
PRIMARY_EXECUTABLE=beam$(TYPEMARKER).smp
endif

ifeq ($(FLAVOR),@PRIMARY_FLAVOR@)
EMULATOR_EXECUTABLE=$(PRIMARY_EXECUTABLE)
else
EMULATOR_EXECUTABLE=$(FLAVOR_EXECUTABLE)
endif

# ----------------------------------------------------------------------

UNIX_ONLY_BUILDS =
ifeq ($(ERLANG_OSTYPE), unix)
UNIX_ONLY_BUILDS =	$(BINDIR)/$(CS_EXECUTABLE)
endif

.PHONY: all
ifdef VOID_EMULATOR
all:
	@echo $(VOID_EMULATOR)' - omitted target all'
else
all: $(BINDIR)/$(EMULATOR_EXECUTABLE) $(BINDIR)/$(EMULATOR_LIB) $(UNIX_ONLY_BUILDS)
endif

$(BINDIR)/$(PRIMARY_EXECUTABLE): $(BINDIR)/$(FLAVOR_EXECUTABLE)
	$(INSTALL_PROGRAM) $< $@
ifeq ($(TARGET), win32)
	$(INSTALL_PROGRAM) $(basename $<).pdb $(basename $@).pdb
endif

include zlib/zlib.mk
include pcre/pcre.mk
include ryu/ryu.mk
include openssl/openssl.mk

$(ERTS_LIB):
	$(V_at)cd $(ERTS_LIB_DIR) && $(MAKE) $(TYPE)

.PHONY: clean
clean:
	$(RM) $(GENERATE)
	$(RM) -r $(TARGET)/*.c $(TARGET)/*.h $(TARGET)/*-GENERATED
	$(RM) -r $(TARGET)/*/*
	$(RM) -r obj/$(TARGET)
	$(RM) -r pcre/obj/$(TARGET) $(PCRE_GENINC)
	$(RM) -r zlib/obj/$(TARGET)
	$(RM) -r ryu/obj/$(TARGET)
	$(RM) -r openssl/obj/$(TARGET)
	$(RM) -r bin/$(TARGET)
	cd $(ERTS_LIB_DIR) && $(MAKE) clean

.PHONY: docs
docs:

# ----------------------------------------------------------------------
include $(ERL_TOP)/make/otp_release_targets.mk

RELSYSDIR = $(RELEASE_PATH)/erts-$(VSN)

RELEASE_INCLUDES = beam/erl_driver.h sys/$(ERLANG_OSTYPE)/driver_int.h beam/erl_nif.h beam/erl_nif_api_funcs.h beam/erl_drv_nif.h
ifeq ($(TARGET),win32)
RELEASE_INCLUDES += sys/$(ERLANG_OSTYPE)/erl_win_dyn_driver.h
endif

.PHONY: release_spec
ifdef VOID_EMULATOR
release_spec:
	@echo $(VOID_EMULATOR)' - omitted target release_spec (install)'
else
release_spec: all
	$(INSTALL_DIR) "$(RELSYSDIR)"
	$(INSTALL_DIR) "$(RELSYSDIR)/src"
	$(INSTALL_DIR) "$(RELSYSDIR)/include"
	$(INSTALL_DIR) "$(RELSYSDIR)/man"
	$(INSTALL_DIR) "$(RELSYSDIR)/doc"
	$(INSTALL_DIR) "$(RELSYSDIR)/bin"
	$(INSTALL_DIR) "$(RELEASE_PATH)/usr/include"
	$(INSTALL_DATA) $(RELEASE_INCLUDES) "$(RELEASE_PATH)/usr/include"
	$(INSTALL_DATA) $(RELEASE_INCLUDES) "$(RELSYSDIR)/include"
	$(INSTALL_PROGRAM) $(BINDIR)/$(EMULATOR_EXECUTABLE) "$(RELSYSDIR)/bin"
ifeq ($(RELEASE_LIBBEAM),yes)
	$(INSTALL_DIR) "$(RELSYSDIR)/lib"
	$(INSTALL_PROGRAM) $(BINDIR)/$(EMULATOR_LIB) "$(RELSYSDIR)/lib"
endif
ifeq ($(ERLANG_OSTYPE), unix)
	$(INSTALL_PROGRAM) $(BINDIR)/$(CS_EXECUTABLE) "$(RELSYSDIR)/bin"
endif
endif

.PHONY: release_docs_spec
release_docs_spec:

# ----------------------------------------------------------------------
# Generated source code. Put in $(TARGET) directory
#

ifneq ($(strip $(CREATE_DIRS)),)
_create_dirs := $(shell mkdir -p $(CREATE_DIRS))
endif


# has to be run after _create_dirs
ifeq ($(TARGET), win32)
TMPVAR := $(shell LANG=C $(PERL) utils/make_compiler_flags -o $(TTF_DIR)/erl_compile_flags.h -v CONFIG_H "N/A" -v CFLAGS "$(CFLAGS)" -v LDFLAGS "$(LDFLAGS)")
else
# We force this to be run every time this makefile is executed
TMPVAR := $(shell LANG=C $(PERL) utils/make_compiler_flags -o $(TTF_DIR)/erl_compile_flags.h -f CONFIG_H "$(ERL_TOP)/erts/$(TARGET)/config.h" -v CFLAGS "$(CFLAGS)" -v LDFLAGS "$(LDFLAGS)")
endif

GENERATE =

ifdef DTRACE_ENABLED
# global.h causes problems by including dtrace-wrapper.h which includes
# the autogenerated erlang_dtrace.h ... so make erlang_dtrace.h very early.
DTRACE_HEADERS = $(TARGET)/erlang_dtrace.h
GENERATE += $(DTRACE_HEADERS)
else
DTRACE_HEADERS = 
endif

$(TTF_DIR)/beam_cold.h \
$(TTF_DIR)/beam_warm.h \
$(TTF_DIR)/beam_hot.h \
$(TTF_DIR)/beam_opcodes.c \
$(TTF_DIR)/beam_opcodes.h \
$(TTF_DIR)/beam_transform.c \
	: $(TTF_DIR)/OPCODES-GENERATED
$(TTF_DIR)/OPCODES-GENERATED: $(OPCODE_TABLES) utils/beam_makeops
	$(gen_verbose)LANG=C $(PERL) utils/beam_makeops \
		-wordsize @EXTERNAL_WORD_SIZE@ \
		-code-model @CODE_MODEL@ \
		-outdir $(TTF_DIR) \
		-jit $(if $(filter jit,$(FLAVOR)),yes,no) \
		-DUSE_VM_PROBES=$(if $(USE_VM_PROBES),1,0) \
		-emulator $(OPCODE_TABLES) && echo $? >$(TTF_DIR)/OPCODES-GENERATED
GENERATE += $(TTF_DIR)/OPCODES-GENERATED

ifeq ($(FLAVOR),jit)
$(TTF_DIR)/beam_asm_global.hpp: beam/jit/$(JIT_ARCH)/beam_asm_global.hpp.pl
	$(gen_verbose)LANG=C $(PERL) $<  > $@
GENERATE += $(TTF_DIR)/beam_asm_global.hpp
endif

# bif and atom table
ATOMS=	beam/atom.names
DIRTY_BIFS = beam/erl_dirty_bif.tab
BIFS =	beam/bif.tab

$(TTF_DIR)/erl_bif_table.c \
$(TTF_DIR)/erl_bif_table.h \
$(TTF_DIR)/erl_bif_list.h \
$(TTF_DIR)/erl_atom_table.c \
$(TTF_DIR)/erl_atom_table.h \
$(TTF_DIR)/erl_guard_bifs.c \
$(TTF_DIR)/erl_dirty_bif_wrap.c \
	: $(TTF_DIR)/TABLES-GENERATED
$(TTF_DIR)/TABLES-GENERATED: $(ATOMS) $(DIRTY_BIFS) $(BIFS) utils/make_tables
	$(gen_verbose)LANG=C $(PERL) utils/make_tables -src $(TTF_DIR) -include $(TTF_DIR)\
		-dst $(DS_TEST) -jit $(if $(filter jit,$(FLAVOR)),yes,no)\
		$(ATOMS) $(DIRTY_BIFS) $(BIFS) && echo $? >$(TTF_DIR)/TABLES-GENERATED
GENERATE += $(TTF_DIR)/TABLES-GENERATED

$(TTF_DIR)/erl_alloc_types.h: beam/erl_alloc.types utils/make_alloc_types
	$(gen_verbose)LANG=C $(PERL) utils/make_alloc_types -src $< -dst $@ $(ENABLE_ALLOC_TYPE_VARS)
GENERATE += $(TTF_DIR)/erl_alloc_types.h

# version include file
$(TARGET)/erl_version.h: ../vsn.mk $(ERL_TOP)/make/$(TARGET)/otp.mk
	$(gen_verbose)LANG=C $(PERL) utils/make_version -o $@ $(SYSTEM_VSN) $(OTP_VERSION) $(VSN)$(SERIALNO) $(TARGET)
GENERATE += $(TARGET)/erl_version.h

# driver table
$(TTF_DIR)/driver_tab.c: Makefile.in utils/make_driver_tab
	$(gen_verbose)LANG=C $(PERL) utils/make_driver_tab -o $@ -nifs $(NIF_OBJS) $(STATIC_NIF_LIBS) -drivers $(DRV_OBJS) $(STATIC_DRIVER_LIBS)
GENERATE += $(TTF_DIR)/driver_tab.c



ifeq ($(TYPE)@EXTERNAL_WORD_SIZE@,debug64)
YCF_DEBUG_FLAG = -debug
MAPS_YCF_OUTPUT=$(TARGET)/erl_map.debug.ycf.h
UTILS_YCF_OUTPUT=$(TARGET)/utils.debug.ycf.h
DB_INSERT_LIST_OUTPUT=$(TARGET)/erl_db_insert_list.debug.ycf.h
else
YCF_DEBUG_FLAG =
MAPS_YCF_OUTPUT=$(TARGET)/erl_map.ycf.h
UTILS_YCF_OUTPUT=$(TARGET)/utils.ycf.h
DB_INSERT_LIST_OUTPUT=$(TARGET)/erl_db_insert_list.ycf.h
endif

DB_INSERT_LIST_YCF_FLAGS=-yield \
		$(YCF_DEBUG_FLAG) \
		-static_aux_funs \
		-only_yielding_funs \
		-f ets_insert_2_list_check \
		-f ets_insert_new_2_list_has_member \
		-f ets_insert_2_list_from_p_heap \
		-f ets_insert_2_list_destroy_copied_dbterms \
		-f ets_insert_2_list_copy_term_list \
		-f ets_insert_new_2_dbterm_list_has_member \
		-f ets_insert_2_list_insert_db_term_list \
		-f ets_insert_2_list \
		-fnoauto ets_insert_2_list_lock_tbl

MAPS_YCF_FLAGS=-yield \
		$(YCF_DEBUG_FLAG) \
		-static_aux_funs \
		-only_yielding_funs \
		-fnoauto maps_keys_1_helper \
		-fnoauto maps_values_1_helper \
		-fnoauto maps_from_keys_2_helper \
		-fnoauto maps_from_list_1_helper \
		-fnoauto hashmap_from_validated_list \
		-f hashmap_keys \
		-f hashmap_values \
		-f hashmap_from_unsorted_array \
		-f hashmap_from_sorted_unique_array \
		-f hashmap_from_chunked_array \
		-fexternal erts_qsort

UTILS_YCF_FLAGS=-yield \
		$(YCF_DEBUG_FLAG) \
		-only_yielding_funs \
		-f erts_qsort \
		-f erts_qsort_helper \
		-f erts_qsort_partion_array
# If the array items are large erts_qsort should also trap in the swap
# function, but this causes terrible performance when the array items
# are small, so one should investigate a fast-path approach
# -f erts_qsort_swap

YCF_EXECUTABLE_PATH=""

ifeq ($(CROSS_COMPILING),no)
YCF_EXECUTABLE_PATH="$(ERL_TOP)/erts/lib_src/yielding_c_fun/bin/$(TARGET)/yielding_c_fun$(EXE_SUFFIX)"
else
## We cannot build a 'yielding_c_fun' that can be executed since we are
## cross compiling. A working bootstrap system of valid version *should*
## be in the path. Find 'yielding_c_fun' in the bootstrap system...
YCF_EXECUTABLE_PATH=`utils/find_cross_ycf`
endif

$(DB_INSERT_LIST_OUTPUT): beam/erl_db.c $(ERTS_LIB)
	$(gen_verbose)$(YCF_EXECUTABLE_PATH) \
		$(DB_INSERT_LIST_YCF_FLAGS) \
		-output_file_name $@ $<
$(MAPS_YCF_OUTPUT): beam/erl_map.c $(ERTS_LIB)
	$(gen_verbose)$(YCF_EXECUTABLE_PATH) \
		$(MAPS_YCF_FLAGS) \
		-output_file_name $@ $<
$(UTILS_YCF_OUTPUT): beam/utils.c $(ERTS_LIB)
	$(gen_verbose)$(YCF_EXECUTABLE_PATH) \
		$(UTILS_YCF_FLAGS) \
		-output_file_name $@ $<

GENERATE += $(DB_INSERT_LIST_OUTPUT) $(MAPS_YCF_OUTPUT) $(UTILS_YCF_OUTPUT)

## ASMJIT source files and headers
ASMJIT_CPP = $(wildcard asmjit/core/*.cpp) $(wildcard asmjit/$(JIT_ARCH)/*.cpp)
ASMJIT_H = $(wildcard asmjit/*.h) $(wildcard asmjit/core/*.h) $(wildcard asmjit/$(JIT_ARCH)/*.h)
ASMJIT_TTF_H = $(foreach HEADER,$(ASMJIT_H),$(TTF_DIR)/$(HEADER))

ifeq ($(FLAVOR),jit)
GENERATE+=$(ASMJIT_TTF_H) $(TTF_DIR)/asmjit/asmjit.hpp
endif

# Preloaded code.
# 
# This list must be consistent with PRE_LOADED_MODULES in
# erts/preloaded/src/Makefile.

ESOCK_PRELOAD_BEAM = \
	$(ERL_TOP)/erts/preloaded/ebin/socket_registry.beam \
	$(ERL_TOP)/erts/preloaded/ebin/prim_socket.beam \
	$(ERL_TOP)/erts/preloaded/ebin/prim_net.beam

PRELOAD_BEAM =	$(ERL_TOP)/erts/preloaded/ebin/erts_code_purger.beam \
		$(ERL_TOP)/erts/preloaded/ebin/erl_init.beam \
		$(ERL_TOP)/erts/preloaded/ebin/init.beam \
		$(ERL_TOP)/erts/preloaded/ebin/prim_buffer.beam \
		$(ERL_TOP)/erts/preloaded/ebin/prim_eval.beam \
		$(ERL_TOP)/erts/preloaded/ebin/prim_inet.beam \
		$(ERL_TOP)/erts/preloaded/ebin/prim_file.beam \
		$(ERL_TOP)/erts/preloaded/ebin/zlib.beam \
		$(ESOCK_PRELOAD_BEAM) \
		$(ERL_TOP)/erts/preloaded/ebin/prim_zip.beam \
		$(ERL_TOP)/erts/preloaded/ebin/erl_prim_loader.beam \
		$(ERL_TOP)/erts/preloaded/ebin/erlang.beam \
		$(ERL_TOP)/erts/preloaded/ebin/erts_internal.beam \
		$(ERL_TOP)/erts/preloaded/ebin/erl_tracer.beam \
		$(ERL_TOP)/erts/preloaded/ebin/erts_literal_area_collector.beam \
		$(ERL_TOP)/erts/preloaded/ebin/erts_dirty_process_signal_handler.beam \
		$(ERL_TOP)/erts/preloaded/ebin/atomics.beam \
		$(ERL_TOP)/erts/preloaded/ebin/counters.beam \
		$(ERL_TOP)/erts/preloaded/ebin/persistent_term.beam

ifeq ($(TARGET),win32)
# On windows the preloaded objects are in a resource object.
PRELOAD_OBJ = $(OBJDIR)/beams.$(RES_EXT)
PRELOAD_SRC = $(TARGET)/beams.rc
$(PRELOAD_SRC): $(PRELOAD_BEAM)
	$(gen_verbose)LANG=C $(PERL) utils/make_preload $(MAKE_PRELOAD_EXTRA) -rc $^ > $@
else
PRELOAD_OBJ = $(OBJDIR)/preload.o
PRELOAD_SRC = $(TARGET)/preload.c
$(PRELOAD_SRC): $(PRELOAD_BEAM)
	$(gen_verbose)LANG=C $(PERL) utils/make_preload -old $^ > $@
endif

.PHONY : generate
ifdef VOID_EMULATOR
generate:
	@echo $(VOID_EMULATOR)' - omitted target generate'
else
generate: $(TTF_DIR)/GENERATED $(PRELOAD_SRC)

$(TTF_DIR)/GENERATED: $(GENERATE)
	$(gen_verbose)echo $? >$(TTF_DIR)/GENERATED

# Regenerate if Makefile has changed
$(GENERATE): $(TARGET)/Makefile

endif

$(TARGET)/erlang_dtrace.h: beam/erlang_dtrace.d
	$(dtrace_verbose)dtrace -h -C -Ibeam -s $< -o ./erlang_dtrace.tmp
	$(V_at)sed -e '/^#define[ 	]*ERLANG_[A-Z0-9_]*(.*)/y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/' ./erlang_dtrace.tmp > $@
	$(V_at)rm ./erlang_dtrace.tmp

# ----------------------------------------------------------------------
# Pattern rules
#
COMMON_INCLUDES = -Ibeam -Isys/$(ERLANG_OSTYPE) -Isys/common -I$(TARGET)
ifndef Z_LIB
COMMON_INCLUDES += -Izlib 
endif
COMMON_INCLUDES += -Ipcre
COMMON_INCLUDES += -Iryu
COMMON_INCLUDES += -Iopenssl/include
COMMON_INCLUDES += -I../include -I../include/$(TARGET)
COMMON_INCLUDES += -I../include/internal -I../include/internal/$(TARGET)

ifeq ($(FLAVOR),jit)
COMMON_INCLUDES += -Ibeam/jit -Ibeam/jit/$(JIT_ARCH)
endif

INCLUDES  =  -I$(TTF_DIR) $(COMMON_INCLUDES)

ifeq ($(TARGET),win32)
$(OBJDIR)/dll_sys.o: sys/$(ERLANG_OSTYPE)/sys.c
	$(V_CC) $(CFLAGS) -DERL_RUN_SHARED_LIB=1 $(INCLUDES) -c $< -o $@

$(OBJDIR)/beams.$(RES_EXT): $(TARGET)/beams.rc
	$(V_RC) -o $@  -I$(ERL_TOP)/erts/etc/win32 $(TARGET)/beams.rc

endif

# We disable the implicit rule of .S -> .o so that the verbose asm
# generate is not used for compiling erts. This is only a problem on
# old solaris make
%.o : %.S

# Usually the same as the default rule, but certain platforms (e.g. win32) mix
# different compilers
$(OBJDIR)/beam_emu.o: beam/emu/beam_emu.c
	$(V_EMU_CC) $(subst -O2, $(GEN_OPT_FLGS), $(CFLAGS)) $(INCLUDES) -c $< -o $@

$(OBJDIR)/beam_emu.S: beam/emu/beam_emu.c
	$(V_EMU_CC) -S -fverbose-asm $(subst -O2, $(GEN_OPT_FLGS), $(CFLAGS)) $(INCLUDES) -c $< -o $@

$(OBJDIR)/%_pg.o: beam/%.c
	$(V_CC) $(PROFILE_GENERATE) $(subst -O2, $(GEN_OPT_FLGS), $(CFLAGS)) $(INCLUDES) -c $< -o $@

$(OBJDIR)/%_pg.o: beam/emu/%.c
	$(V_CC) $(PROFILE_GENERATE) $(subst -O2, $(GEN_OPT_FLGS), $(CFLAGS)) $(INCLUDES) -c $< -o $@

$(OBJDIR)/%_pu.o: beam/%.c $(PROFILE_USE_DEPS)
	$(V_CC) $(PROFILE_USE) $(subst -O2, $(GEN_OPT_FLGS), $(CFLAGS)) $(INCLUDES) -c $< -o $@

$(OBJDIR)/%_pu.o: beam/emu/%.c $(PROFILE_USE_DEPS)
	$(V_CC) $(PROFILE_USE) $(subst -O2, $(GEN_OPT_FLGS), $(CFLAGS)) $(INCLUDES) -c $< -o $@

$(OBJDIR)/%_pu.S: beam/%.c $(PROFILE_USE_DEPS)
	$(V_CC) -S -fverbose-asm $(PROFILE_USE) $(subst -O2, $(GEN_OPT_FLGS), $(CFLAGS)) $(INCLUDES) -c $< -o $@

$(OBJDIR)/%_pu.S: beam/emu/%.c $(PROFILE_USE_DEPS)
	$(V_CC) -S -fverbose-asm $(PROFILE_USE) $(subst -O2, $(GEN_OPT_FLGS), $(CFLAGS)) $(INCLUDES) -c $< -o $@

$(OBJDIR)/PROFILE: $(BINDIR)/$(PROFILE_EXECUTABLE)
	$(V_at)echo " PROFILE ${PROFILE_EXECUTABLE}"
	$(V_at)rm -f $(OBJDIR)/erl*.profraw
	$(V_at)set -e; LLVM_PROFILE_FILE="$(OBJDIR)/erlc-%m.profraw" \
          ERL_FLAGS="-emu_flavor ${FLAVOR} -emu_type prof${TYPEMARKER} +S 1" $(ERLC) -no-server \
          -DPGO -o $(OBJDIR) test/estone_SUITE.erl > $(OBJDIR)/PROFILE_LOG
	$(V_at)set -e; LLVM_PROFILE_FILE="$(OBJDIR)/erl-%m.profraw" \
	  ERL_FLAGS="-emu_flavor ${FLAVOR} -emu_type prof${TYPEMARKER} +S 1" $(ERL) -pa $(OBJDIR) \
	  -noshell -s estone_SUITE pgo -s init stop >> $(OBJDIR)/PROFILE_LOG
	$(V_at)touch $@

.SECONDARY: $(patsubst %.o,%_pu.gcda,$(PROFILE_OBJS))

$(OBJDIR)/%_pu.gcda: $(OBJDIR)/PROFILE
	$(V_at)mv $(OBJDIR)/$*_pg.gcda $@
	$(V_at)touch $@

$(OBJDIR)/default.profdata: $(OBJDIR)/PROFILE
	$(V_LLVM_PROFDATA) merge -output $@ $(OBJDIR)/*.profraw

ifeq ($(ERTS_BUILD_FALLBACK_POLL),yes)
# Have to treat erl_poll differently as the same .c file is used
# twice for kernel poll builds.
$(OBJDIR)/erl_poll.o: sys/common/erl_poll.c
	$(V_CC) -DERTS_KERNEL_POLL_VERSION $(subst -O2, $(GEN_OPT_FLGS), $(CFLAGS)) $(INCLUDES) -c $< -o $@

# Do a copy in order to make debuggers less confused
$(TTF_DIR)/erl_poll.flbk.c: sys/common/erl_poll.c
	$(V_at) cp $< $@
	@touch $@

$(OBJDIR)/erl_poll.flbk.o: $(TTF_DIR)/erl_poll.flbk.c
	$(V_CC) -DERTS_NO_KERNEL_POLL_VERSION $(subst -O2, $(GEN_OPT_FLGS), $(CFLAGS)) $(INCLUDES) -c $< -o $@
endif


# ----------------------------------------------------------------------
# General targets
#
$(OBJDIR)/%.o: beam/%.c
	$(V_CC) $(subst -O2, $(GEN_OPT_FLGS), $(CFLAGS)) $(INCLUDES) -c $< -o $@

$(OBJDIR)/%.o: beam/emu/%.c
	$(V_CC) $(subst -O2, $(GEN_OPT_FLGS), $(CFLAGS)) $(INCLUDES) -c $< -o $@

$(OBJDIR)/%.o: beam/jit/%.c
	$(V_CC) $(subst -O2, $(GEN_OPT_FLGS), $(CFLAGS)) $(INCLUDES) -c $< -o $@

$(OBJDIR)/%.o: $(TARGET)/%.c
	$(V_CC) $(CFLAGS) $(INCLUDES) -Idrivers/common -c $< -o $@

$(OBJDIR)/%.o: $(TTF_DIR)/%.c
	$(V_CC) $(CFLAGS) $(INCLUDES) -c $< -o $@

$(OBJDIR)/%.o: sys/$(ERLANG_OSTYPE)/%.c
	$(V_CC) $(CFLAGS) $(INCLUDES) -c $< -o $@

$(OBJDIR)/%.o: sys/common/%.c
	$(V_CC) $(subst -O2, $(GEN_OPT_FLGS), $(CFLAGS)) $(INCLUDES) -c $< -o $@

$(OBJDIR)/%.o: drivers/common/%.c
	$(V_CC) $(CFLAGS) -DLIBSCTP=$(LIBSCTP) $(INCLUDES) -Idrivers/common -Idrivers/$(ERLANG_OSTYPE) -c $< -o $@

$(OBJDIR)/%.o: drivers/$(ERLANG_OSTYPE)/%.c
	$(V_CC) $(CFLAGS) $(INCLUDES) -Idrivers/common -Idrivers/$(ERLANG_OSTYPE) -I../etc/$(ERLANG_OSTYPE) -c $< -o $@

$(OBJDIR)/%.o: nifs/common/%.c
	$(V_CC) $(CFLAGS) -DLIBSCTP=$(LIBSCTP) $(INCLUDES) -Inifs/common -Inifs/$(ERLANG_OSTYPE) -c $< -o $@

$(OBJDIR)/%.o: nifs/$(ERLANG_OSTYPE)/%.c
	$(V_CC) $(CFLAGS) $(INCLUDES) -Inifs/common -Inifs/$(ERLANG_OSTYPE) -I../etc/$(ERLANG_OSTYPE) -c $< -o $@

#
# Build the beamasm sources.
#
# Note that we #include the asmjit header directly on the command line
# because GCC only allows one precompiled header, and requires it to be
# included before any other directives, including other #includes.
#
ASMJIT_FLAGS=-DASMJIT_EMBED=1 -DASMJIT_NO_BUILDER=1 -DASMJIT_NO_DEPRECATED=1 -DASMJIT_STATIC=1 -DASMJIT_NO_FOREIGN=1

ASMJIT_PCH_OBJ=$(TTF_DIR)/asmjit/asmjit.hpp.gch
ASMJIT_PCH_SRC=$(TTF_DIR)/asmjit/asmjit.hpp

$(OBJDIR)/%.o: beam/jit/%.cpp $(ASMJIT_PCH_OBJ)
	$(V_CXX) $(ASMJIT_FLAGS) $(INCLUDES)                        \
          $(subst -O2, $(GEN_OPT_FLGS), $(CXXFLAGS))                \
          -include $(ASMJIT_PCH_SRC) -c $< -o $@

$(OBJDIR)/%.o: beam/jit/$(JIT_ARCH)/%.cpp beam/jit/$(JIT_ARCH)/beam_asm.hpp $(ASMJIT_PCH_OBJ)
	$(V_CXX) $(ASMJIT_FLAGS) $(INCLUDES)                        \
          $(subst -O2, $(GEN_OPT_FLGS), $(CXXFLAGS))                \
          -include $(ASMJIT_PCH_SRC) -c $< -o $@

$(OBJDIR)/asmjit/%.o: asmjit/%.cpp $(ASMJIT_PCH_OBJ) $(dir $@)
	$(V_CXX) $(ASMJIT_FLAGS) $(INCLUDES)                        \
          $(subst -O2, $(GEN_OPT_FLGS), $(CXXFLAGS))                \
          -include $(ASMJIT_PCH_SRC) -c $< -o $@

## The dependency on erl_bif_info.c is in order to trigger a rebuild when
## the git sha define on the command line argument changes
$(ASMJIT_PCH_OBJ): $(ASMJIT_PCH_SRC) $(ASMJIT_TTF_H) beam/erl_bif_info.c
	$(V_CXX) $(ASMJIT_FLAGS) $(INCLUDES)                        \
          $(subst -O2, $(GEN_OPT_FLGS), $(CXXFLAGS))                \
          -I$(TTF_DIR) -c $< -o $@

## We copy all asmjit headers into TTF_DIR in order for cross-compilation
## with pre-compiled header to work.
$(TTF_DIR)/asmjit/asmjit.hpp: asmjit/asmjit.h
	$(V_at)cp $< $@
$(TTF_DIR)/asmjit/%.h: asmjit/%.h
	$(V_at)cp $< $@

.PHONY: update_asmjit
update_asmjit:
	git clone git@github.com:asmjit/asmjit -b master asmjit-copy
	(cd asmjit-copy && git rev-parse --verify HEAD) > asmjit.version
	rm -rf asmjit
	cp -r asmjit-copy/src/asmjit asmjit
	cp asmjit-copy/*.md asmjit/
	git add asmjit asmjit.version
	rm -rf asmjit-copy

# ----------------------------------------------------------------------
# Specials
#
CS_OBJ = $(OBJDIR)/erl_child_setup.o $(OBJDIR)/sys_uds.o $(OBJDIR)/hash.o

$(BINDIR)/$(CS_EXECUTABLE): $(TTF_DIR)/GENERATED $(PRELOAD_SRC) $(CS_OBJ) $(ERTS_LIB)
	$(ld_verbose) $(LD) $(CS_LDFLAGS) -o $(BINDIR)/$(CS_EXECUTABLE) \
               $(CS_CFLAGS) $(COMMON_INCLUDES) $(CS_OBJ) $(CS_LIBS)

ifeq ($(GCC),yes)

$(OBJDIR)/erl_goodfit_alloc.o: beam/erl_goodfit_alloc.c
	$(V_CC) $(subst -O2, $(GEN_OPT_FLGS) $(UNROLL_FLG), $(CFLAGS)) $(INCLUDES) -c $< -o $@
endif

# ----------------------------------------------------------------------
# Build necessary beam files if they are not already in place. To force
# rebuilding (is this a good idea?) add a dummy dependency to this target.
#

$(ERL_TOP)/lib/%.beam:
	cd $(@D)/../src && $(MAKE) ../ebin/$(@F)


# ----------------------------------------------------------------------
# Object files
#

INIT_OBJS = $(OBJDIR)/erl_main.o	$(PRELOAD_OBJ)

PROFILE_OBJS = $(OBJDIR)/erl_process.o
ifneq ($(JIT_ENABLED),yes)
PROFILE_OBJS += $(OBJDIR)/beam_emu.o
endif

COMMON_OBJS = \
    $(OBJDIR)/beam_common.o \
    $(OBJDIR)/beam_bif_load.o \
    $(OBJDIR)/beam_bp.o \
    $(OBJDIR)/beam_catches.o \
    $(OBJDIR)/beam_debug.o \
    $(OBJDIR)/beam_load.o \
    $(OBJDIR)/beam_opcodes.o \
    $(OBJDIR)/beam_ranges.o \
    $(OBJDIR)/beam_transform.o \
    $(OBJDIR)/beam_transform_engine.o \
    $(OBJDIR)/beam_transform_helpers.o \
    $(OBJDIR)/code_ix.o

ASMJIT_OBJS = $(patsubst %.cpp,$(OBJDIR)/%.o,$(ASMJIT_CPP))

JIT_OBJS = \
    $(OBJDIR)/asm_load.o \
    $(OBJDIR)/beam_asm_global.o \
    $(OBJDIR)/beam_asm_module.o \
    $(OBJDIR)/beam_jit_common.o \
    $(OBJDIR)/beam_jit_main.o \
    $(OBJDIR)/beam_jit_metadata.o \
    $(OBJDIR)/process_main.o

ifeq ($(JIT_ARCH), x86)
JIT_OBJS += \
	$(OBJDIR)/instr_arith.o \
	$(OBJDIR)/instr_bs.o \
	$(OBJDIR)/instr_bif.o \
	$(OBJDIR)/instr_call.o \
	$(OBJDIR)/instr_common.o \
	$(OBJDIR)/instr_float.o \
	$(OBJDIR)/instr_fun.o \
	$(OBJDIR)/instr_guard_bifs.o \
	$(OBJDIR)/instr_map.o \
	$(OBJDIR)/instr_msg.o \
	$(OBJDIR)/instr_select.o \
	$(OBJDIR)/instr_trace.o
else
JIT_OBJS += \
	$(OBJDIR)/instr_arith.o \
	$(OBJDIR)/instr_bs.o \
	$(OBJDIR)/instr_bif.o \
	$(OBJDIR)/instr_call.o \
	$(OBJDIR)/instr_common.o \
	$(OBJDIR)/instr_float.o \
	$(OBJDIR)/instr_fun.o \
	$(OBJDIR)/instr_guard_bifs.o \
	$(OBJDIR)/instr_map.o \
	$(OBJDIR)/instr_msg.o \
	$(OBJDIR)/instr_select.o \
	$(OBJDIR)/instr_trace.o
endif

JIT_OBJS += $(ASMJIT_OBJS)

EMU_OBJS = \
	$(OBJDIR)/emu_load.o

ESOCK_NIF_OBJS = \
	$(OBJDIR)/prim_socket_nif.o \
	$(OBJDIR)/prim_net_nif.o

ESOCK_RUN_OBJS = \
	$(OBJDIR)/socket_dbg.o \
	$(OBJDIR)/socket_tarray.o \
	$(OBJDIR)/socket_util.o

RUN_OBJS += \
	$(OBJDIR)/erl_alloc.o \
	$(OBJDIR)/erl_alloc_util.o	$(OBJDIR)/erl_goodfit_alloc.o \
	$(OBJDIR)/erl_bestfit_alloc.o	$(OBJDIR)/erl_afit_alloc.o \
	$(OBJDIR)/erl_init.o \
	$(OBJDIR)/erl_atom_table.o	$(OBJDIR)/erl_bif_table.o \
	$(OBJDIR)/erl_bif_ddll.o  	$(OBJDIR)/erl_bif_guard.o \
	$(OBJDIR)/erl_bif_info.o	$(OBJDIR)/erl_bif_op.o \
	$(OBJDIR)/erl_bif_os.o		$(OBJDIR)/erl_bif_lists.o \
	$(OBJDIR)/erl_bif_persistent.o \
	$(OBJDIR)/erl_bif_atomics.o    	$(OBJDIR)/erl_bif_counters.o \
	$(OBJDIR)/erl_bif_trace.o	$(OBJDIR)/erl_bif_unique.o \
	$(OBJDIR)/erl_guard_bifs.o 	$(OBJDIR)/erl_dirty_bif_wrap.o \
	$(OBJDIR)/erl_trace.o		$(OBJDIR)/copy.o \
	$(OBJDIR)/utils.o		$(OBJDIR)/bif.o \
	$(OBJDIR)/io.o 			$(OBJDIR)/erl_printf_term.o\
	$(OBJDIR)/erl_debug.o \
	$(OBJDIR)/erl_message.o		$(OBJDIR)/erl_proc_sig_queue.o \
	$(OBJDIR)/erl_process_dict.o	$(OBJDIR)/erl_process_lock.o \
	$(OBJDIR)/erl_port_task.o	$(OBJDIR)/erl_arith.o \
	$(OBJDIR)/time.o		$(OBJDIR)/erl_time_sup.o  \
	$(OBJDIR)/external.o		$(OBJDIR)/dist.o \
	$(OBJDIR)/binary.o		$(OBJDIR)/erl_db.o \
	$(OBJDIR)/erl_db_util.o		$(OBJDIR)/erl_db_hash.o \
	$(OBJDIR)/erl_db_tree.o		$(OBJDIR)/erl_thr_progress.o \
	$(OBJDIR)/big.o			$(OBJDIR)/hash.o \
	$(OBJDIR)/index.o		$(OBJDIR)/atom.o \
	$(OBJDIR)/module.o		$(OBJDIR)/export.o \
	$(OBJDIR)/register.o		$(OBJDIR)/break.o \
	$(OBJDIR)/erl_async.o		$(OBJDIR)/erl_lock_check.o \
	$(OBJDIR)/erl_dyn_lock_check.o \
	$(OBJDIR)/erl_gc.o 		$(OBJDIR)/erl_lock_count.o \
	$(OBJDIR)/erl_posix_str.o	\
	$(OBJDIR)/erl_bits.o 		$(OBJDIR)/erl_math.o \
	$(OBJDIR)/erl_fun.o             $(OBJDIR)/erl_bif_port.o \
	$(OBJDIR)/erl_term.o 		$(OBJDIR)/erl_node_tables.o \
	$(OBJDIR)/erl_monitor_link.o	$(OBJDIR)/erl_process_dump.o \
	$(OBJDIR)/erl_hl_timer.o	$(OBJDIR)/erl_cpu_topology.o \
	$(OBJDIR)/erl_drv_thread.o      $(OBJDIR)/erl_bif_chksum.o \
	$(OBJDIR)/erl_bif_re.o		$(OBJDIR)/erl_unicode.o \
	$(OBJDIR)/packet_parser.o	$(OBJDIR)/safe_hash.o \
	$(OBJDIR)/erl_zlib.o		$(OBJDIR)/erl_nif.o \
	$(OBJDIR)/erl_bif_binary.o      $(OBJDIR)/erl_ao_firstfit_alloc.o \
	$(OBJDIR)/erl_thr_queue.o	$(OBJDIR)/erl_sched_spec_pre_alloc.o \
	$(OBJDIR)/erl_ptab.o		$(OBJDIR)/erl_map.o \
	$(OBJDIR)/erl_msacc.o		$(OBJDIR)/erl_lock_flags.o \
	$(OBJDIR)/erl_io_queue.o	$(OBJDIR)/erl_db_catree.o \
	$(ESOCK_RUN_OBJS)		$(OBJDIR)/erl_flxctr.o \
	$(OBJDIR)/erl_nfunc_sched.o \
	$(OBJDIR)/erl_global_literals.o \
	$(OBJDIR)/beam_file.o \
	$(OBJDIR)/beam_types.o \
	$(OBJDIR)/erl_term_hashing.o

LTTNG_OBJS = $(OBJDIR)/erlang_lttng.o

NIF_OBJS = \
	$(OBJDIR)/prim_tty_nif.o \
	$(OBJDIR)/erl_tracer_nif.o \
	$(OBJDIR)/prim_buffer_nif.o \
	$(OBJDIR)/prim_file_nif.o \
	$(OBJDIR)/zlib_nif.o \
	$(ESOCK_NIF_OBJS)

ifeq ($(TARGET),win32)
DRV_OBJS = \
	$(OBJDIR)/registry_drv.o \
	$(OBJDIR)/inet_drv.o \
	$(OBJDIR)/ram_file_drv.o
OS_OBJS = \
	$(OBJDIR)/dll_sys.o \
	$(OBJDIR)/driver_tab.o \
	$(OBJDIR)/sys_float.o \
	$(OBJDIR)/sys_time.o \
	$(OBJDIR)/sys_interrupt.o \
	$(OBJDIR)/sys_env.o \
	$(OBJDIR)/dosmap.o \
	$(OBJDIR)/win_prim_file.o \
	$(OBJDIR)/win_socket_asyncio.o

else
OS_OBJS = \
	$(OBJDIR)/sys.o \
	$(OBJDIR)/sys_drivers.o \
	$(OBJDIR)/sys_env.o \
	$(OBJDIR)/sys_uds.o \
	$(OBJDIR)/driver_tab.o \
	$(OBJDIR)/unix_prim_file.o \
	$(OBJDIR)/sys_float.o \
	$(OBJDIR)/sys_time.o \
	$(OBJDIR)/sys_signal_stack.o \
	$(OBJDIR)/unix_socket_syncio.o

DRV_OBJS = \
	$(OBJDIR)/inet_drv.o \
	$(OBJDIR)/ram_file_drv.o
endif

ifneq ($(STATIC_NIFS),no)
STATIC_NIF_LIBS = $(STATIC_NIFS)
DEPLIBS += $(STATIC_NIF_LIBS)
COMPILE_STATIC_LIBS = yes
else
STATIC_NIF_LIBS=
endif

ifneq ($(STATIC_DRIVERS),no)
STATIC_DRIVER_LIBS = $(STATIC_DRIVERS)
DEPLIBS += $(STATIC_DRIVER_LIBS)
COMPILE_STATIC_LIBS = yes
else
STATIC_DRIVER_LIBS=
endif

ifeq ($(COMPILE_STATIC_LIBS),yes)

$(STATIC_NIF_LIBS) $(STATIC_DRIVER_LIBS):
	echo "=== Entering lib to make static libs"
	(cd $(ERL_TOP)/lib/ && $(MAKE) BUILD_STATIC_LIBS=1 TYPE=$(TYPE) static_lib)
	echo "=== Leaving lib after making static libs"
endif

OS_OBJS +=	$(OBJDIR)/erl_poll.o \
		$(OBJDIR)/erl_check_io.o \
		$(OBJDIR)/erl_mseg.o \
		$(OBJDIR)/erl_mmap.o  \
		$(OBJDIR)/erl_osenv.o \
		$(OBJDIR)/erl_$(ERLANG_OSTYPE)_sys_ddll.o \
		$(OBJDIR)/erl_sys_common_misc.o \
		$(OBJDIR)/erl_os_monotonic_time_extender.o

ifeq ($(ERTS_BUILD_FALLBACK_POLL),yes)
OS_OBJS += 	$(OBJDIR)/erl_poll.flbk.o
endif

ifeq ($(JIT_ENABLED),yes)
BASE_OBJS = $(JIT_OBJS)
else
BASE_OBJS = $(EMU_OBJS)
endif

BASE_OBJS += $(COMMON_OBJS) $(RUN_OBJS) $(OS_OBJS) $(EXTRA_BASE_OBJS) \
	$(LTTNG_OBJS) $(DRV_OBJS) $(NIF_OBJS)

PROF_OBJS = $(patsubst %.o,%$(PROFILE_MARKER).o,$(PROFILE_OBJS)) $(BASE_OBJS)

OBJS = $(PROF_OBJS)

ifdef DTRACE_ENABLED_2STEP
# The $(PROFILE_MARKER) is placed in the object file name in order to
# make sure we re-compile with the new object files for the profiled emulator
OBJS += $(OBJDIR)/erlang$(PROFILE_MARKER)_dtrace.o
$(OBJDIR)/erlang$(PROFILE_MARKER)_dtrace.o: $(PROF_OBJS) $(TARGET)/erlang_dtrace.h
	dtrace -G -C -Ibeam \
	  -s beam/erlang_dtrace.d \
	  -o $@ $(PROF_OBJS)
endif

$(INIT_OBJS): $(TTF_DIR)/GENERATED
$(OBJS): $(TTF_DIR)/GENERATED

# ----------------------------------------------------------------------
# The emulator itself
#

ifeq ($(TARGET), win32)
# Only the basic erlang to begin with eh?
$(BINDIR)/$(FLAVOR_EXECUTABLE): $(INIT_OBJS) $(OBJS) $(DEPLIBS)
	$(ld_verbose) $(LD) -dll -def:sys/$(ERLANG_OSTYPE)/erl.def \
	-implib:$(BINDIR)/erl_dll.lib -o $@ \
	$(LDFLAGS) $(DEXPORT) $(INIT_OBJS) $(OBJS) $(STATIC_NIF_LIBS) \
	$(STATIC_DRIVER_LIBS) $(LIBS)

else
ifeq ($(FLAVOR),jit)
EMU_LD=$(CXX)
else
EMU_LD=$(CC)
endif
$(BINDIR)/$(FLAVOR_EXECUTABLE): $(INIT_OBJS) $(OBJS) $(DEPLIBS)
	$(ld_verbose) $(EMU_LD) -o $@ \
	$(PROFILE_LDFLAGS) $(LDFLAGS) $(DEXPORT) $(INIT_OBJS) $(OBJS) \
	$(STATIC_NIF_LIBS) $(STATIC_DRIVER_LIBS) $(LIBS)

endif

# ----------------------------------------------------------------------
# The emulator as a static lib ...
#
ifeq ($(USING_VC),yes)
AR_OUT=-out:
AR_FLAGS=
else
AR_OUT=
ifeq ($(V),0)
AR_FLAGS=rc
else
AR_FLAGS=rcv
endif
endif

$(BINDIR)/${EMULATOR_LIB}: $(PRELOAD_OBJ) $(OBJS) $(DEPLIBS)
	$(V_AR) $(AR_FLAGS) $(AR_OUT)$@ \
	$(PRELOAD_OBJ) $(OBJS)
	$(V_RANLIB) $@

# ----------------------------------------------------------------------
# Dependencies
#
$(TARGET)/Makefile: Makefile.in
	@echo
	@echo "Makefile.in has been updated, please re-run configure!"
	@echo
	@exit 1

#SED_REPL_WIN_DRIVE=s|\([ 	]\)\([A-Za-z]\):|\1/cygdrive/\2|g;s|^\([A-Za-z]\):|/cygdrive/\1|g
SED_REPL_O=s|^\([^:]*:\)|$$(OBJDIR)/\1|g
SED_REPL_O_ZLIB=s|^\([^:]*:\)|$$(ZLIB_OBJDIR)/\1|g
SED_REPL_TTF_DIR=s|$(TTF_DIR)/|$$(TTF_DIR)/|g
SED_REPL_ERL_TOP=s|\([ 	]\)$(ERL_TOP)/|\1$$(ERL_TOP)/|g;s|^$(ERL_TOP)/|$$(ERL_TOP)/|g
SED_REPL_POLL=s|$$(OBJDIR)/erl_poll.o|$$(OBJDIR)/erl_poll.o $$(OBJDIR)/erl_poll.flbk.o|g
SED_REPL_TTF_COMP_FLAGS=s|\([^/]\)erl_compile_flags\.h|\1$$(TTF_DIR)/erl_compile_flags\.h|g
SED_ASMJIT_HPP_FLAGS=s|\([^/]\)asmjit/asmjit\.hpp|\1$$(TTF_DIR)/asmjit/asmjit\.hpp|g

ifeq ($(TARGET),win32)
#SED_PREFIX=$(SED_REPL_WIN_DRIVE);
SED_PREFIX=
else
SED_PREFIX=
endif

ifeq ($(ERTS_BUILD_FALLBACK_POLL),yes)
SED_SUFFIX=;$(SED_REPL_POLL)
else
SED_SUFFIX=
endif

SED_DEPEND=sed '$(SED_PREFIX)$(SED_REPL_O);$(SED_REPL_TTF_DIR);$(SED_REPL_ERL_TOP)$(SED_SUFFIX);$(SED_REPL_TTF_COMP_FLAGS);$(SED_ASMJIT_HPP_FLAGS)'
SED_DEPEND_ZLIB=sed '$(SED_PREFIX)$(SED_REPL_O_ZLIB)'

BEAM_SRC=$(wildcard beam/*.c)
ifeq ($(FLAVOR),emu)
BEAM_SRC+=$(wildcard beam/emu/*.c)
else
BEAM_CPP_SRC=$(wildcard beam/*.cpp) $(wildcard beam/jit/*.cpp) $(wildcard beam/jit/$(JIT_ARCH)/*.cpp)
endif
DRV_COMMON_SRC=$(wildcard drivers/common/*.c)
DRV_OSTYPE_SRC=$(wildcard drivers/$(ERLANG_OSTYPE)/*.c)
ifeq ($(TARGET), win32)
# These are *currently* only needed for non-win32,
# since the nif-functions for socket and net are basically
# stubbed with badarg in the win32 case.
NIF_COMMON_SRC=$(filter-out $(wildcard nifs/common/socket_*.c), $(wildcard nifs/common/*.c))
else
NIF_COMMON_SRC=$(wildcard nifs/common/*.c)
endif
NIF_OSTYPE_SRC=$(wildcard nifs/$(ERLANG_OSTYPE)/*.c)
ALL_SYS_SRC=$(wildcard sys/$(ERLANG_OSTYPE)/*.c) $(wildcard sys/common/*.c)
# We use $(shell find) here instead of wildcard as $(wildcard ) resolved at
# loadtime of the makefile and at that time these files are not generated yet.
TARGET_SRC=$(shell find $(TARGET) $(TTF_DIR) -maxdepth 1 -name "*.c")

# I do not want the -MG flag on windows, it does not work properly for a 
# windows build.

ifeq ($(TARGET),win32)

#DEP_CC=$(EMU_CC)
DEP_CC=$(CC)
DEP_CXX=$(CXX)
DEP_INCLUDES=$(INCLUDES) -I../etc/win32 \
	-Idrivers/common -Idrivers/$(ERLANG_OSTYPE) \
	-Inifs/common -Inifs/$(ERLANG_OSTYPE)
DEP_FLAGS=-MM  $(subst -O2,,$(CFLAGS)) $(INCLUDES) 
DEP_CXXFLAGS=-MM $(subst -O2,,$(CXXFLAGS)) $(DEP_INCLUDES) $(ASMJIT_FLAGS)

# ifeq ($(USING_VC),yes)
# VC++ used for compiling. If __GNUC__ is defined we will include
# other headers then when compiling which will result in faulty
# dependencies.
# DEP_FLAGS += -U__GNUC__
# endif
# On windows we have the erl_poll implementation in sys/win32 (no longer...)
# SYS_SRC=$(subst sys/common/erl_poll.c,,$(ALL_SYS_SRC))

else # !win32

ifeq ($(findstring tile,$(TARGET)),tile)
# tile-gcc doesn't like -MG
MG_FLAG=
else
MG_FLAG=-MG
endif

DEP_CC=$(CC)
DEP_CXX=$(CXX)
DEP_INCLUDES=$(INCLUDES) \
	-Idrivers/common -Idrivers/$(ERLANG_OSTYPE) \
	-Inifs/common -Inifs/$(ERLANG_OSTYPE)
DEP_FLAGS=-MM $(MG_FLAG) $(CFLAGS) $(DEP_INCLUDES)
DEP_CXXFLAGS=-MM $(MG_FLAG) $(CXXFLAGS) $(DEP_INCLUDES) $(ASMJIT_FLAGS)
SYS_SRC=$(ALL_SYS_SRC)
endif

.PHONY: check_emu_registers
check_emu_registers: $(OBJDIR)/beam_emu$(PROFILE_MARKER).S
	utils/beam_emu_vars -vars 'c_p E HTOP FCALLS I reg' $^

.PHONY: $(TARGET)/gen_git_version.mk
$(TARGET)/gen_git_version.mk:
# We touch beam/erl_bif.info.c if we regenerated the git version to force a
# rebuild.
	$(V_at)if utils/gen_git_version $@; then touch beam/erl_bif_info.c; fi

DEPEND_DEPS=jit src drv nif sys target zlib ryu

$(TTF_DIR)/src.depend.mk: $(TTF_DIR)/GENERATED $(PRELOAD_SRC)
	$(gen_verbose)
	$(V_at)$(DEP_CC) $(DEP_FLAGS) $(BEAM_SRC) \
		| $(SED_DEPEND) > $@
$(TTF_DIR)/drv.depend.mk: $(TTF_DIR)/GENERATED $(PRELOAD_SRC)
	$(gen_verbose)
	$(V_at)$(DEP_CC) $(DEP_FLAGS) -DLIBSCTP=$(LIBSCTP) $(DRV_COMMON_SRC) \
		| $(SED_DEPEND) > $@
	$(V_at)$(DEP_CC) $(DEP_FLAGS) -I../etc/$(ERLANG_OSTYPE) $(DRV_OSTYPE_SRC) \
		| $(SED_DEPEND) >> $@
$(TTF_DIR)/nif.depend.mk: $(TTF_DIR)/GENERATED $(PRELOAD_SRC)
	$(gen_verbose)
	$(V_at)$(DEP_CC) $(DEP_FLAGS) $(NIF_COMMON_SRC) \
		| $(SED_DEPEND) > $@
	$(V_at)$(DEP_CC) $(DEP_FLAGS) -I../etc/$(ERLANG_OSTYPE) $(NIF_OSTYPE_SRC) \
		| $(SED_DEPEND) >> $@
$(TTF_DIR)/sys.depend.mk: $(TTF_DIR)/GENERATED $(PRELOAD_SRC)
	$(gen_verbose)
	$(V_at)$(DEP_CC) $(DEP_FLAGS) $(SYS_SRC) \
		| $(SED_DEPEND) > $@
$(TTF_DIR)/target.depend.mk: $(TTF_DIR)/GENERATED $(PRELOAD_SRC)
	$(gen_verbose)
	$(V_at)$(DEP_CC) $(DEP_FLAGS) $(TARGET_SRC) \
		| $(SED_DEPEND) > $@
$(TTF_DIR)/zlib.depend.mk: $(TTF_DIR)/GENERATED $(PRELOAD_SRC)
	$(gen_verbose)
	$(V_at)$(DEP_CC) $(DEP_FLAGS) $(ZLIB_SRC) \
		| $(SED_DEPEND_ZLIB) > $@
$(TTF_DIR)/ryu.depend.mk: $(TTF_DIR)/GENERATED $(PRELOAD_SRC)
	$(gen_verbose)
	$(V_at)$(DEP_CC) $(DEP_FLAGS) $(RYU_SRC) \
		| $(SED_DEPEND_ZLIB) > $@
$(TTF_DIR)/jit.depend.mk: $(TTF_DIR)/GENERATED $(PRELOAD_SRC)
	$(gen_verbose)
	@touch $@
ifeq ($(JIT_ENABLED),yes)
	$(V_at)$(DEP_CXX) $(DEP_CXXFLAGS) $(BEAM_CPP_SRC) \
		| $(SED_DEPEND) > $@
endif

.PHONY: depend
ifdef VOID_EMULATOR
depend:
	@echo $(VOID_EMULATOR)' - omitted target depend'
else
depend: $(TTF_DIR)/depend.mk
$(TTF_DIR)/depend.mk: $(foreach dep, $(DEPEND_DEPS), $(TTF_DIR)/$(dep).depend.mk)
	$(gen_verbose)
	$(V_at)echo "" > "$@"
	$(V_at)for dep in "$^"; do cat $$dep >> "$@"; done
	$(V_at)cd $(ERTS_LIB_DIR) && $(MAKE) depend
endif

COMPDB_CFLAGS=-MM $(filter-out -fno-tree-copyrename,$(CFLAGS)) $(DEP_INCLUDES)
COMPDB_CXXFLAGS=-MM $(filter-out -fno-tree-copyrename,$(CXXFLAGS)) $(DEP_INCLUDES) $(ASMJIT_FLAGS)

compdb:
	clang -MJ $(TTF_DIR)/beam.json $(COMPDB_CFLAGS) $(BEAM_SRC) > /dev/null
	clang++ -MJ $(TTF_DIR)/beam.cpp.json $(COMPDB_CXXFLAGS) $(BEAM_CPP_SRC) > /dev/null
	clang -MJ $(TTF_DIR)/drv.json $(COMPDB_CFLAGS) -DLIBSCTP=$(LIBSCTP) $(DRV_COMMON_SRC) > /dev/null
	clang -MJ $(TTF_DIR)/drv_$(ERLANG_OSTYPE).json \
		$(COMPDB_CFLAGS) -I../etc/$(ERLANG_OSTYPE) $(DRV_OSTYPE_SRC) > /dev/null
	clang -MJ $(TTF_DIR)/nif.json $(COMPDB_CFLAGS) $(NIF_COMMON_SRC)  > /dev/null
	clang -MJ $(TTF_DIR)/nif_$(ERLANG_OSTYPE).json \
		$(COMPDB_CFLAGS) -I../etc/$(ERLANG_OSTYPE) $(NIF_OSTYPE_SRC) > /dev/null
	clang -MJ $(TTF_DIR)/sys.json $(COMPDB_CFLAGS) $(SYS_SRC) > /dev/null
	clang -MJ $(TTF_DIR)/target.json $(COMPDB_CFLAGS) $(TARGET_SRC) > /dev/null
	clang -MJ $(TTF_DIR)/zlib.json $(COMPDB_CFLAGS) $(ZLIB_SRC) > /dev/null
	cat $(TTF_DIR)/*.json > $(ERL_TOP)/compile_commands.json

format-check:
	clang-format --Werror --dry-run -i beam/jit/*.hpp beam/jit/*.c beam/jit/*.h \
            beam/jit/*.cpp beam/jit/*/*.cpp beam/jit/*/*.hpp

format:
	clang-format -i beam/jit/*.hpp beam/jit/*.c beam/jit/*.h \
            beam/jit/*.cpp beam/jit/*/*.cpp beam/jit/*/*.hpp

ifneq ($(ERTS_SKIP_DEPEND),true)
ifneq ($(MAKECMDGOALS),clean)
ifneq ($(MAKECMDGOALS),generate)
ifndef VOID_EMULATOR
-include $(TTF_DIR)/depend.mk
endif
endif
endif
endif

include $(ERL_TOP)/make/app_targets.mk
